項目56 型の表示に配慮する
ライブラリを使用する場合、型をどのように表示するかによって、使用感が変わってくるため、作者は型の表示に配慮する必要がある
どんな型であれ、それを表示する多くの有効な方法がある
ユニオン型は通常、その構成要素をリスとした順に表示する
code:ts
type T123 = '1' | '2' | '3';
// ^? type T123 = "1" | "2" | "3"
しかし、オーバーラップする既存のユニオンがたまたまあった場合は、異なる表示になることがある
code:ts
type T21 = '2' | '1';
// ^? type T21 = "2" | "1"
type T123 = '1' | '2' | '3';
// ^? type T123 = "2" | "1" | "3"
ジェネリック型を解決して、わかりやすい表示をできるようにする
下記のコードは型の表示がわかりにくい例
PartCommentの型がどのようにジェネリック型を利用しているのかにフォーカスされていて、具体的な型がわかりにくい
code:ts
// オブジェクトの一部のプロパティをオプショナルにするジェネリック型
type PartiallyPartial<T, K extends keyof T> =
Partial<Pick<T, K>> & Omit<T, K>;
interface BlogComment {
commentId: number;
title: string;
content: string;
}
type PartComment = PartiallyPartial<BlogComment, 'title'>;
// ^? type PartComment =
// Partial<Pick<BlogComment, "title">> &
// Omit<BlogComment, "title">
型プログラミングを解決させる型を作って対応する
Resolve型としてその仕組を作る
code:ts
type Resolve<T> = T extends Function ? T : {K in keyof T: TK};
code:ts
type PartiallyPartial<T, K extends keyof T> =
Resolve<Partial<Pick<T, K>> & Omit<T, K>>;
type PartComment = PartiallyPartial<BlogComment, 'title'>;
// ^? type PartComment = {
// title?: string | undefined;
// commentId: number;
// content: string;
// }
型をきれい表示したい重要な特殊ケースも存在する
型パラメータのKがneverのケース
code:ts
type FullComment = PartiallyPartial<BlogComment, never>;
// ^? type FullComment = {
// title: string;
// commentId: number;
// content: string;
// }
上記のコードは、型表示としてはBlogCommentを表示するべき。そのために条件型を使ってneverの場合の考慮を行う
code:ts
type PartiallyPartial<T extends object, K extends keyof T> =
K extends never
? T // 特別なケース
: Resolve<Partial<Pick<T, K>> & Omit<T, K>>;
type FullComment = PartiallyPartial<BlogComment, never>;
// ^? type FullComment = BlogComment
型表示の調整に使われる、他のテクニックもあるが、Resolveに置き換えることができる
Exclude<keyof T, never>によるkeyofを使った型のインライン表示
unknown & Tまたは{} & Tによる、オブジェクト型のインライン表示
#TypeScript